/**
 * All rights reserved by www.xmerge.cn
 */
package net.xfok.xmerge.parser;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import net.xfok.http.client.HttpClient;
import net.xfok.xmerge.provider.RssItem;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import android.util.Log;

/**
 * @author YangHua
 *
 */
public class RssParser {	
	public final static HttpClient CLIENT=new HttpClient();
	
	static final String TAG = "RssParser";
	
    static final String NODE_RSS_CHANEL = "chanel";
    static final String NODE_RSS_NAME = "name";
    static final String NODE_RSS_LINK = "link";
    static final String NODE_RSS_CHARSET = "charset";
    
    static final Set<String> fetchChars = new HashSet<String>();

    static {
        fetchChars.add(NODE_RSS_CHANEL);
        fetchChars.add(NODE_RSS_NAME);
        fetchChars.add(NODE_RSS_LINK);
        fetchChars.add(NODE_RSS_CHARSET);
    }
	      
    private List<RssItem> rssItems;
    private RssItem currentItem = null;
    private StringBuilder cache = new StringBuilder(4096);
    
    public RssParser(InputStream is){
    	rssItems=this.getRssItems(is);
    }
    
    public RssParser(String url){
    	rssItems=this.getRssItems(url);
    }
    
    public List<RssItem> getRssItems() {
    	return this.rssItems;
    }
    
    private List<RssItem> getRssItems(String url) {
    	InputStream is=post(url);
    	return getRssItems(is);
    }
    
    private List<RssItem> getRssItems(InputStream is) {
    	if(is!=null){
    		try{
    			rssItems=new ArrayList<RssItem>();
    			RssParserHandler handler=new RssParserHandler();
    			SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
    			SAXParser parser = saxParserFactory.newSAXParser();
    			Log.i(TAG, "parse start");
    			parser.parse(is, handler);
    			Log.i(TAG, "parse end");
    		}catch(Exception e){
    			e.printStackTrace();
    		}
    	}
    	return rssItems;
    }
    
    private InputStream post(String url){
		InputStream is=null;
		try{
			is =CLIENT.request(url);
		}catch(Exception e){
			e.printStackTrace();
		}
		return is;
	}
  
	private class RssParserHandler extends DefaultHandler {
		@Override
		public void characters(char[] ch, int start, int length)
				throws SAXException {
			if(cache!=null){
				 cache.append(ch, start, length);
			}
		}
		
		@Override
		public void startElement(String uri, String localName, String qName,
				Attributes attr) throws SAXException {		
			if(localName.equals(NODE_RSS_CHANEL)){
				currentItem = new RssItem();
			}
			if (fetchChars.contains(localName)){
				cache = new StringBuilder(1024);
			}else{
				cache = null;
			}
		}
		
		@Override
		public void endElement(String uri, String localName, String qName)
				throws SAXException {
			if(localName.equals(NODE_RSS_CHANEL)){
	            rssItems.add(currentItem);
	            currentItem = null;
	        }
            if (currentItem!=null&&cache!=null) {
                if (NODE_RSS_NAME.equals(localName)){
                    currentItem.setName(cache.toString());
                }
                if (NODE_RSS_LINK.equals(localName)){
                    currentItem.setUrl(cache.toString());
                }              
                if (NODE_RSS_CHARSET.equals(localName)){
                    currentItem.setCharset(cache.toString());
                }      
            }
		}
	}
}
